﻿namespace FietsenManagementJB
{
    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.Linq;
    using System.Windows.Forms;

    class BikeController
    {
        private SortableBindingList<Bike> bikes;
        private Bike activeBike;
        private List<Tuple<ValidationType, Control>> registeredForValidation;

        public BikeController()
        {
            bikes = new SortableBindingList<Bike>();
            registeredForValidation = new List<Tuple<ValidationType, Control>>();
        }

        public SortableBindingList<Bike> importProcedure()
        {
            var import = new ImportHelper();
            bikes = import.importProcedure();
            foreach (var bike in bikes)
            {
                bike.Id = GenId();
                bike.Sold = bike.SellDate != DateTime.MinValue ? true : false;
                bike.BikePicture = "testfiets1.jpg";
                var balance = bike.SellPrice - (bike.BuyPrice + bike.InvestmentPrice);
                bike.Balance = balance;
            }
            return bikes;
        }

        public SortableBindingList<Bike> LoadBikes()
        {
            bikes = IOModule.readDBFile(bikes);
            return bikes;
        }

        public bool saveNewBike(string gender, string buy, string sell, string location, string invest, 
            DateTime? selldate, string frame, string framenr)
        {
            var bike = new Bike(GenId(), "Nieuwe naam", gender, DateTime.Now, decimal.Parse(buy), decimal.Zero, 
                location, decimal.Zero, DateTime.MinValue, activeBike.BikePicture, int.Parse(frame), framenr,
                CalcBalance(), false);
            bikes.Add(bike);
            CopyLocalImage();
            return bikes.Contains(bike);
        }

        public bool updateActiveBike(string name, string gender, DateTime buydate, string buy, string sell, string location, 
            string invest, DateTime? selldate, string frame, string framenr, bool sold)
        {
            var bike = new Bike(activeBike.Id, name, gender, buydate, decimal.Parse(buy), decimal.Parse(sell),
                location, decimal.Parse(invest), selldate.Value, activeBike.BikePicture, int.Parse(frame), framenr
                ,CalcBalance() , sold);
            bikes.Remove(activeBike);
            bikes.Add(bike);
            CopyLocalImage();
            return bikes.Contains(bike);
        }

        public Tuple<bool, List<string>> inputValidation()
        {
            var allFieldsValid = true;
            var invalidValidationMessages = new List<string>();
            foreach (var fieldToBeValidated in registeredForValidation)
            {
                switch (fieldToBeValidated.Item1)
                {
                    case ValidationType.NumericCurrency:
                        if (!TryParseDecimalOrInt(typeof(decimal), ((TextBox)fieldToBeValidated.Item2)))
                        {
                            allFieldsValid = false;
                            invalidValidationMessages.Add("Veld moet numeriek zijn, " + fieldToBeValidated.Item2.Text + " is een geen goede waarde.");
                        }
                        if (!fieldToBeValidated.Item2.Text.StartsWith("€"))
                        {
                            fieldToBeValidated.Item2.BackColor = Color.Red;
                            allFieldsValid = false;
                            invalidValidationMessages.Add("Het formaat " + fieldToBeValidated.Item2.Text + " is een geen goede waarde.");
                        }
                        break;
                    case ValidationType.NotNull:
                        if (fieldToBeValidated.Item2.Text == "")
                        {
                            allFieldsValid = false;
                            fieldToBeValidated.Item2.BackColor = Color.Red;
                            invalidValidationMessages.Add("Veld mag niet leeg zijn");
                        }
                        break;
                    case ValidationType.Numeric:
                        if (!TryParseDecimalOrInt(typeof(int), ((TextBox)fieldToBeValidated.Item2)))
                        {
                            allFieldsValid = false;
                            fieldToBeValidated.Item2.BackColor = Color.Red;
                            invalidValidationMessages.Add("Veld moet numeriek zijn, " + fieldToBeValidated.Item2.Text + " is een geen goede waarde.");
                        }
                        break;
                }
                if (allFieldsValid)
                    fieldToBeValidated.Item2.BackColor = Color.White;
            }
            return new Tuple<bool, List<string>>(allFieldsValid, invalidValidationMessages);
        }

        private int GenId()
        {
            var random = new Random(DateTime.Now.Millisecond);
            var uniqueID = random.Next() % 1000000;
            while (bikes.Any(x => x.Id == uniqueID))
            {
                uniqueID = random.Next() % 1000000;
            }
            return uniqueID;
        }

        public Bike LoadBike(int id)
        {
            var bike = bikes.First(x => x.Id == id);
            if (bike != null)
            {
                activeBike = bike;
                return bike;
            }
            else
            {
                return null;
            }
        }

        public bool TryParseDecimalOrInt(Type type, TextBox textbox)
        {
            var validated = true;
            if (textbox.Text.Length < 1)
                return false;
            if (type == typeof(decimal))
            {
                decimal i;
                // Substring(1) for euro sign 
                if (!decimal.TryParse(textbox.Text.Substring(1), out i))
                {
                    textbox.BackColor = Color.Red;
                    validated = false;
                }
            }
            if (type == typeof(int))
            {
                int i;
                if (!int.TryParse(textbox.Text, out i))
                {
                    textbox.BackColor = Color.Red;
                    MessageBox.Show(String.Format("Veld moet een numerieke waarde bevatten. Zonder komma waardes"));
                    validated = false;
                }
            }
            return validated;
        }

        public decimal CalcBalance()
        {
            this.ActiveBike.Balance = (activeBike.SellPrice - (activeBike.BuyPrice + activeBike.InvestmentPrice));
            return this.ActiveBike.Balance;
        }

        public SortableBindingList<Bike> DeleteActiveBike()
        {
            bikes.Remove(activeBike);
            IOModule.writeDBFile(bikes);
            return bikes;
        }

        public bool CopyLocalImage()
        {
            var newLoc = GenerateLocalFile();
            if (!IOModule.fileExists(newLoc))
            {
                return IOModule.copyImageFile(newLoc, activeBike.BikePicture);
            }
            return false;
        }

        private string GenerateLocalFile()
        {
            var imgloc = activeBike.BikePicture.Split(new char[] { '\\' });
            return imgloc[imgloc.Length - 1];
        }

        public void SaveBikes()
        {
            IOModule.writeDBFile(bikes);
        }

        public bool CreateBackup()
        {
            var newBackupName = "BackUpFietsenBestand.txt";
            var increment = 0;
            while (IOModule.fileExists(newBackupName))
            {
                increment++;
                newBackupName = "BackUpFietsenBestand(" + increment + ").txt";
            }
            return IOModule.copyImageFile(newBackupName, "BikeDB.txt");
        }

        #region Accessors

        internal SortableBindingList<Bike> Bikes
        {
            get { return bikes; }
            set { bikes = value; }
        }

        internal Bike ActiveBike
        {
            get { return activeBike; }
            set { activeBike = value; }
        }

        public List<Tuple<ValidationType, Control>> RegisteredForValidation
        {
            get { return registeredForValidation; }
            set { registeredForValidation = value; }
        }

        #endregion

    }
}
